/**
 * 
 */
package com.sudoku;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * @author chinhnq
 * 
 */
public class Game extends Activity implements OnClickListener{
	
	public static final String KEY_DIFFICULTY = "com.sudoku";
	public static final int DIFFICULTY_EASY = 0;
	public static final int DIFFICULTY_MEDIUM = 1;
	public static final int DIFFICULTY_HARD = 2;
	
	private int difficulty[];
	 /** Cache of used tiles */
	private final int used[][][] = new int[9][9][];
	
	private final String easyPuzzle = "650000070000506000014000005007009000002314700000700800500000630000201000030000097";
	private final String mediumPuzzle = "650000070000506000014000005007009000002314700000700800500000630000201000030000097";
	private final String hardPuzzle = "009000000080605020501078000000000700706040102004000000000720903090301080000000600";
	
	private GridGUIGame gridGUIGame;
	
	private final Button keys[] = new Button[9];
	private View keypad;
	private int tiles[];
	Typeface typeFont, typeFontChica;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			
			
			
			int diff = getIntent().getIntExtra(KEY_DIFFICULTY, DIFFICULTY_EASY);
			difficulty = getDifficulty(diff);
			
			calculateUsedTiles();
			gridGUIGame = new GridGUIGame(this);
			setContentView(R.layout.gridgame);//
			gridGUIGame.requestFocus();
			gridGUIGame.setFocusable(true);
			
			findViews();
  	       setListeners();
		   typeFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/chiller.ttf");
		   typeFontChica = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/chicago_house.ttf");
  	       Button clean = (Button) findViewById(R.id.clean);  	       
  	       clean.setOnClickListener(this);
  	       clean.setTypeface(typeFont);
		   
  	       TextView difiiculty = (TextView) findViewById(R.id.difficulty);
  	       TextView time = (TextView) findViewById(R.id.time);
  	       difiiculty.setTypeface(typeFont);
  	       time.setTypeface(typeFont);
  	       gridGUIGame = (GridGUIGame) findViewById(R.id.gridgame);
  	       gridGUIGame.requestFocus();
  	       
	}
	
	/**
	 * Convert a puzzle string into an array
	 * @param diff
	 * @return
	 */
	static protected int[] fromDifficultyString(String diff) {

		int[] puz = new int[diff.length()];
		for (int i = 0; i < puz.length; i++) {
			puz[i] = diff.charAt(i) - '0';
		}
		return puz;

	}
	/**
	 * Given a difficulty level, come up with a new puzzle
	 * @param difficulty
	 * @return
	 */
	private int[] getDifficulty(int difficulty){
		String diff = "";
		
		switch(difficulty){
		case DIFFICULTY_EASY:
			diff = easyPuzzle;
			break;
		case DIFFICULTY_MEDIUM:
			diff = mediumPuzzle;
			break;
		case DIFFICULTY_HARD:
			diff = hardPuzzle;
			break;			
		}
		
		return fromDifficultyString(diff);
	}
	/**
	 * Return the tile at the given coordinates
	 * @param x
	 * @param y
	 * @return
	 */
	private int getTile(int x, int y){
		return difficulty[y * 9 + x];
	}
	
	/**
	 * Set value position
	 * @param x
	 * @param y
	 * @param tile
	 */
	private void setTile(int x, int y, int tile){
		
		difficulty[y * 9 + x] = tile;
	}
		
	/**
	 * Return a string for the tile at the given coordinates
	 * @param x
	 * @param y
	 * @return
	 */
	protected String getTileString(int x, int y){
		int value = getTile(x, y);
		if(value == 0)
			return "";
		else
			return String.valueOf(value);
	}
	/**
	 * Change the tile only if it's a valid move
	 * 
	 * @param x
	 * @param y
	 * @param value
	 * @return
	 */
	protected boolean setTileIfValid(int x, int y, int value) {
		int tiles[] = getUsedTiles(x, y);
		if (value != 0) {
			Log.w("SET", value+"");
			for (int tile : tiles) {
				if (tile == value)
					return false;
			}
		}
		setTile(x, y, value);
		calculateUsedTiles();
		return true;
	}

	/**
	 * 
	 * Return cached used tiles visible from the given coords
	 * 
	 * @param x is row
	 * @param y is column
	 * @return
	 */
	protected int[] getUsedTiles(int x, int y){
		//Log.w("getused[x][y]", "used[x][y]="+x+","+y);
		return used[x][y];
	}
	
	/**
	 * 
	 * Compute the two dimensional array of used tiles
	 * 
	 */
	private void calculateUsedTiles(){
		for(int x = 0; x < 9; x++){
			for(int y = 0; y < 9; y++){
				used[x][y] = calculateUsedTiles(x, y);
				//Log.w("setused[x][y]", "used[x][y]="+x+","+y);
			}
		}
	}
	
	/**
	 * Compute the used tiles visible from this position
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	private int[] calculateUsedTiles(int x, int y) {
		int c[] = new int[9];
		// horizontal
		for (int i = 0; i < 9; i++) {
			if (i == x)
				continue;
			int t = getTile(i, y);
			if (t != 0)
				c[t - 1] = t;
		}
		// vertical
		for (int i = 0; i < 9; i++) {
			if (i == y)
				continue;
			int t = getTile(x, i);
			if (t != 0)
				c[t - 1] = t;
		}
		// same cell block
		int startx = (x / 3) * 3;
		int starty = (y / 3) * 3;
		for (int i = startx; i < startx + 3; i++) {
			for (int j = starty; j < starty + 3; j++) {
				if (i == x && j == y)
					continue;
				int t = getTile(i, j);
				if (t != 0)
					c[t - 1] = t;
			}
		}
		// compress
		int nused = 0;
		for (int t : c) {
			if (t != 0)
				nused++;
		}
		int c1[] = new int[nused];
		nused = 0;
		for (int t : c) {
			if (t != 0)
				c1[nused++] = t;
		}
		return c1;
	}
	   /** Open the keypad if there are any valid moves */
	   protected void showKeypadOrError(int x, int y) {
		   tiles = getUsedTiles(x, y);
		   
	      if (tiles.length == 9) {
	         Toast toast = Toast.makeText(this,
	               R.string.no_moves_label, Toast.LENGTH_SHORT);
	         toast.setGravity(Gravity.CENTER, 0, 0);
	         toast.show();
	      } else {
//	         Log.d("Error", "showKeypad: used=" + toPuzzleString(tiles));
//	         Dialog v = new Keypad(this, tiles, gridGUIGame);
//	         v.show();
	    	  reSetAll(keys,true);
		      for (int element : tiles) {		    	  
		    	  //Log.w("element", element+"");
		          if (element != 0){
	        		  keys[element - 1].setEnabled(false);//setVisibility(View.INVISIBLE);
		          	//Log.w("KEYPRESS", (element - 1)+"");
      		  
	        		  }

		       }	    	  

	      }		
		         
	   }
	   /** Convert an array into a puzzle string */
	   static private String toPuzzleString(int[] puz) {
	      StringBuilder buf = new StringBuilder();
	      for (int element : puz) {
	         buf.append(element);
	      }
	      return buf.toString();
	   }	
	   
	   public void reSetAll(View key[], boolean isEndable){
		   for(int i = 0; i < key.length; i++){
			   key[i].setEnabled(isEndable);
		   }
	   }
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		int tile = 0;
		switch (keyCode) {
		case KeyEvent.KEYCODE_0:
		case KeyEvent.KEYCODE_SPACE:
			tile = 0;
			break;
		case KeyEvent.KEYCODE_1:
			tile = 1;
			break;
		case KeyEvent.KEYCODE_2:
			tile = 2;
			break;
		case KeyEvent.KEYCODE_3:
			tile = 3;
			break;
		case KeyEvent.KEYCODE_4:
			tile = 4;
			break;
		case KeyEvent.KEYCODE_5:
			tile = 5;
			break;
		case KeyEvent.KEYCODE_6:
			tile = 6;
			break;
		case KeyEvent.KEYCODE_7:
			tile = 7;
			break;
		case KeyEvent.KEYCODE_8:
			tile = 8;
			break;
		case KeyEvent.KEYCODE_9:
			tile = 9;
			break;
		default:
			return super.onKeyDown(keyCode, event);
		}
		if (isValid(tile)) {
			gridGUIGame.setSelectedTile(tile);
			
		}
		return true;
	}
	
	private boolean isValid(int tile) {
		for (int t : tiles) {
			if (tile == t)
			{Log.w("isValid", tile+"");
				return false;
			}
		}
		return true;
	}

	/**
	 * Find button id from xml file
	 */
	private void findViews() {
		keypad = findViewById(R.id.keypad);
		keys[0] = (Button)findViewById(R.id.keypad_1);
		keys[1] = (Button)findViewById(R.id.keypad_2);
		keys[2] = (Button)findViewById(R.id.keypad_3);
		keys[3] = (Button)findViewById(R.id.keypad_4);
		keys[4] = (Button)findViewById(R.id.keypad_5);
		keys[5] = (Button)findViewById(R.id.keypad_6);
		keys[6] = (Button)findViewById(R.id.keypad_7);
		keys[7] = (Button)findViewById(R.id.keypad_8);
		keys[8] = (Button)findViewById(R.id.keypad_9);
//		keys[9] = findViewById(R.id.clean);
//		keys[10] = findViewById(R.id.undo);
//		keys[11] = findViewById(R.id.redo); 
	}
	/**
	 * Set listener for button
	 */
	private void setListeners() {
		Log.d("LENGHT", keys.length+"");
		for (int i = 0; i < keys.length; i++) {
			final int t = i + 1;
			keys[i].setOnClickListener(new View.OnClickListener() {
				public void onClick(View v) {
	
					gridGUIGame.setSelectedTile(t);
					
				}
			});
		}
		keypad.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				gridGUIGame.setSelectedTile(0);
				
			}
		});
	}

	public void setColorButton(){
		reSetAll(keys, false);
		for(int i = 0 ; i < keys.length; i++){
		
			if(keys[i].isEnabled() == true){
				keys[i].setTypeface(typeFont, Typeface.BOLD);
				keys[i].setTextSize(18f);
				keys[i].setTextColor(Color.RED);
				
			}	
			//Log.w("ENDABLE", keys[i].isEnabled()+"");
		}
	}
	public void onClick(View v) {
		int tile = 0;
		switch(v.getId()){
		
		case R.id.clean:
			Log.d("DEBUG", "DACHON");
			tile = 0;
			gridGUIGame.setSelectedTile(tile);
			
			break;
		}
		
	}
	

}
